home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / pine3.07 / pico / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-14  |  18.1 KB  |  643 lines

  1. /*
  2.  * Program:    High level file input and output routines
  3.  *
  4.  * Modifier:    Michael Seibel
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: mikes@cac.washington.edu
  11.  *
  12.  * Date:    19 Jan 1991
  13.  * Last Edited:    6 Jan 1992
  14.  *
  15.  * Copyright 1991 by the University of Washington
  16.  *
  17.  *  Permission to use, copy, modify, and distribute this software and its
  18.  * documentation for any purpose and without fee is hereby granted, provided
  19.  * that the above copyright notice appears in all copies and that both the
  20.  * above copyright notice and this permission notice appear in supporting
  21.  * documentation, and that the name of the University of Washington not be
  22.  * used in advertising or publicity pertaining to distribution of the software
  23.  * without specific, written prior permission.  This software is made
  24.  * available "as is", and
  25.  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
  26.  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
  27.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
  28.  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
  29.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  30.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
  31.  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
  32.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33.  *
  34.  */
  35. /*
  36.  * The routines in this file
  37.  * handle the reading and writing of
  38.  * disk files. All of details about the
  39.  * reading and writing of the disk are
  40.  * in "fileio.c".
  41.  */
  42. #include        <stdio.h>
  43. #include    "osdep.h"
  44. #include    "estruct.h"
  45. #include        "edef.h"
  46. #include        "pico.h"
  47.  
  48.  
  49. /*
  50.  * some useful external declarations
  51.  */
  52. extern char *gethomedir();
  53.  
  54.  
  55. /*
  56.  * Read a file into the current
  57.  * buffer. This is really easy; all you do it
  58.  * find the name of the file, and call the standard
  59.  * "read a file into the current buffer" code.
  60.  * Bound to "C-X C-R".
  61.  */
  62. fileread(f, n)
  63. {
  64.         register int    s;
  65.         char fname[NFILEN];
  66.  
  67.         if ((s=mlreply("Read file: ", fname, NFILEN, QFFILE)) != TRUE)
  68.                 return(s);
  69.  
  70.     if(gmode&MDSCUR){
  71.         emlwrite("File reading disabled in secure mode",NULL);
  72.         return(0);
  73.     }
  74.  
  75.         return(readin(fname, TRUE));
  76. }
  77.  
  78.  
  79.  
  80.  
  81. static char *inshelptext[] = {
  82.   "Insert File Help Text",
  83.   " ",
  84.   "\tType in a file name to have it inserted into your editing",
  85.   "\tbuffer between the line that the cursor is currently on",
  86.   "\tand the line directly below it.  You may abort this by ",
  87.   "~\ttyping the ~F~3 (~^~C) key after exiting help.",
  88.   " ",
  89.   "End of Insert File Help",
  90.   " ",
  91.   NULL
  92. };
  93.  
  94. static char *writehelp[] = {
  95.   "Write File Help Text",
  96.   " ",
  97.   "\tType in a file name to have it written out, thus saving",
  98.   "\tyour buffer, to a file.  You can abort this by typing ",
  99.   "~\tthe ~F~3 (~^~C) key after exiting help.",
  100.   " ",
  101.   "End of Write File Help",
  102.   " ",
  103.   " ",
  104.   NULL
  105. };
  106.  
  107.  
  108. /*
  109.  * Insert a file into the current
  110.  * buffer. This is really easy; all you do it
  111.  * find the name of the file, and call the standard
  112.  * "insert a file into the current buffer" code.
  113.  * Bound to "C-X C-I".
  114.  */
  115. insfile(f, n)
  116. {
  117.         register int    s;
  118.         char fname[NFILEN], dir[NFILEN];
  119.         int    retval, bye = 0;
  120.         char    *prompt = "Insert file: ";
  121.         register int    availen;
  122.  
  123.         availen = term.t_ncol - strlen(prompt);
  124.  
  125.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  126.         return(rdonly());    /* we are in read only mode    */
  127.  
  128.         fname[0] = '\0';
  129.         while(!bye){
  130.             wkeyhelp("GC00000T0000","Get Help,Cancel,To Files");
  131.  
  132.         if(Pmaster == NULL)
  133.           sgarbk = TRUE;
  134.  
  135.             if ((s=mlreplyd(prompt,fname,NFILEN,QDEFLT|QFFILE)) != TRUE){
  136.         switch(s){
  137.           case (CTRL|'T'):
  138.             if(*fname && isdir(fname, NULL))
  139.               strcpy(dir, fname);
  140.             else
  141.               strcpy(dir, gethomedir(NULL));
  142.  
  143.             if((s = FileBrowse(dir, fname, NULL)) == 1){
  144.             if(gmode&MDSCUR){
  145.                 emlwrite("Can't insert file in restricted mode",
  146.                      NULL);
  147.                 sleep(2);
  148.             }
  149.             else{
  150.                 strcat(dir, S_FILESEP);
  151.                 strcat(dir, fname);
  152.                 retval = ifile(dir);
  153.             }
  154.             bye++;
  155.             }
  156.             else
  157.               fname[0] = '\0';
  158.  
  159.             refresh(FALSE, 1);
  160.             if(s != 1){
  161.             update();         /* redraw on return */
  162.             continue;
  163.             }
  164.             break;
  165.           case HELPCH:
  166.             if(Pmaster){
  167.             (*Pmaster->helper)(Pmaster->ins_help,
  168.                        "Help for Insert File", 1);
  169.             }
  170.             else
  171.               pico_help(inshelptext, "Help for Insert File", 1);
  172.           case (CTRL|'L'):
  173.             refresh(FALSE, 1);
  174.             update();
  175.             continue;
  176.           default:
  177.                     retval = s;
  178.             bye++;
  179.         }
  180.             }
  181.             else{
  182.         bye++;
  183.         if(gmode&MDSCUR){
  184.             emlwrite("Can't insert file in restricted mode",NULL);
  185.         }
  186.         else{
  187.             fixpath(fname, NFILEN);
  188.             retval = ifile(fname);
  189.         }
  190.             }
  191.         }
  192.         curwp->w_flag |= WFMODE|WFHARD;
  193.  
  194.         return(retval);
  195. }
  196.  
  197.  
  198. /*
  199.  * Read file "fname" into the current
  200.  * buffer, blowing away any text found there. Called
  201.  * by both the read and find commands. Return the final
  202.  * status of the read. Also called by the mainline,
  203.  * to read in a file specified on the command line as
  204.  * an argument. If the filename ends in a ".c", CMODE is
  205.  * set for the current buffer.
  206.  */
  207. readin(fname, lockfl)
  208.  
  209. char    fname[];    /* name of file to read */
  210. int    lockfl;        /* check for file locks? */
  211.  
  212. {
  213.         register LINE   *lp1;
  214.         register LINE   *lp2;
  215.         register int    i;
  216.         register WINDOW *wp;
  217.         register BUFFER *bp;
  218.         register int    s;
  219.         register int    nbytes;
  220.         register int    nline;
  221.     register char    *sptr;        /* pointer into filename string */
  222.     int        lflag;        /* any lines longer than allowed? */
  223.         char            line[NLINE];
  224.  
  225.         bp = curbp;                             /* Cheap.               */
  226.         if ((s=bclear(bp)) != TRUE)             /* Might be old.        */
  227.                 return (s);
  228.         bp->b_flag &= ~(BFTEMP|BFCHG);
  229.     /* removed 'C' mode detection */
  230.         strcpy(bp->b_fname, fname);
  231.         if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
  232.                 goto out;
  233.         if (s == FIOFNF) {                      /* File not found.      */
  234.                 emlwrite("New file");
  235.                 goto out;
  236.         }
  237.         emlwrite("Reading file");
  238.         nline = 0;
  239.     lflag = FALSE;
  240.         while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
  241.         if (s == FIOLNG)
  242.             lflag = TRUE;
  243.                 nbytes = strlen(line);
  244.                 if ((lp1=lalloc(nbytes)) == NULL) {
  245.                         s = FIOERR;             /* Keep message on the  */
  246.                         break;                  /* display.             */
  247.                 }
  248.                 lp2 = lback(curbp->b_linep);
  249.                 lp2->l_fp = lp1;
  250.                 lp1->l_fp = curbp->b_linep;
  251.                 lp1->l_bp = lp2;
  252.                 curbp->b_linep->l_bp = lp1;
  253.                 for (i=0; i<nbytes; ++i)
  254.                         lputc(lp1, i, line[i]);
  255.                 ++nline;
  256.         }
  257.         ffclose();                              /* Ignore errors.       */
  258.         if (s == FIOEOF) {                      /* Don't zap message!   */
  259.                 sprintf(line,"Read %d line%s", nline, (nline > 1) ? "s" : "");
  260.                 emlwrite(line);
  261.         }
  262.     if (lflag){
  263.         sprintf(line,"Read %d line%s, Long lines wrapped",
  264.             nline, (nline > 1) ? "s" : "");
  265.                 emlwrite(line);
  266.         }
  267. out:
  268.         for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  269.                 if (wp->w_bufp == curbp) {
  270.                         wp->w_linep = lforw(curbp->b_linep);
  271.                         wp->w_dotp  = lforw(curbp->b_linep);
  272.                         wp->w_doto  = 0;
  273.                         wp->w_markp = NULL;
  274.                         wp->w_marko = 0;
  275.  
  276.             if(Pmaster)
  277.               wp->w_flag |= WFHARD;
  278.             else
  279.               wp->w_flag |= WFMODE|WFHARD;
  280.                 }
  281.         }
  282.         if (s == FIOERR || s == FIOFNF)        /* False if error.      */
  283.                 return(FALSE);
  284.         return (TRUE);
  285. }
  286.  
  287.  
  288. /*
  289.  * Ask for a file name, and write the
  290.  * contents of the current buffer to that file.
  291.  * Update the remembered file name and clear the
  292.  * buffer changed flag. This handling of file names
  293.  * is different from the earlier versions, and
  294.  * is more compatable with Gosling EMACS than
  295.  * with ITS EMACS. Bound to "C-X C-W".
  296.  */
  297. filewrite(f, n)
  298. {
  299.         register WINDOW *wp;
  300.         register int    s;
  301.         char            fname[NFILEN];
  302.     char    shows[128], *bufp;
  303.     long    l;        /* length returned from fexist() */
  304.  
  305.     if(curbp->b_fname[0] != 0)
  306.       strcpy(fname, curbp->b_fname);
  307.     else
  308.       fname[0] = '\0';
  309.  
  310.     for(;;){
  311.  
  312.         wkeyhelp("GC00000T0000","Get Help,Cancel,To Files");
  313.         sgarbk = TRUE;
  314.  
  315.         s=mlreplyd("File Name to write : ", fname, NFILEN, QDEFLT|QFFILE);
  316.  
  317.         fixpath(fname, NFILEN);        /*  fixup ~ in file name  */
  318.  
  319.         switch(s){
  320.           case FALSE:
  321.         if(strlen(fname) == 0)        /* no file name to write to */
  322.           return(s);
  323.           case TRUE:
  324.         break;
  325.           case (CTRL|'T'):
  326.         if(*fname && isdir(fname, NULL))
  327.           strcpy(shows, fname);
  328.         else
  329.           strcpy(shows, gethomedir(NULL));
  330.  
  331.         s = FileBrowse(shows, fname, NULL);
  332.         strcat(shows, S_FILESEP);
  333.         strcat(shows, fname);
  334.         strcpy(fname, shows);
  335.  
  336.         refresh(FALSE, 1);
  337.         update();
  338.         if(s == 1)
  339.           break;
  340.         else
  341.           continue;
  342.           case HELPCH:
  343.         pico_help(writehelp, "", 1);
  344.           case (CTRL|'L'):
  345.         refresh(FALSE, 1);
  346.         update();
  347.         continue;
  348.           default:
  349.         return(s);
  350.         break;
  351.         }
  352.  
  353.         if(strcmp(fname, curbp->b_fname) == 0)
  354.         break;
  355.  
  356.         if((s=fexist(fname, "w", &l)) == FIOSUC){ /* exists.  overwrite? */
  357.  
  358.         sprintf(shows, "File \"%s\" exists, OVERWRITE", fname);
  359.         if((s=mlyesno(shows, FALSE)) != TRUE){
  360.             if((bufp = strrchr(fname,'/')) == NULL)
  361.               fname[0] = '\0';
  362.             else
  363.               *++bufp = '\0';
  364.         }
  365.         else
  366.           break;
  367.         }
  368.         else if(s == FIOFNF){
  369.         break;                /* go write it */
  370.         }
  371.         else{                /* some error, can't write */
  372.         fioperr(s, fname);
  373.         return(ABORT);
  374.         }
  375.     }
  376.     emlwrite("Writing...");
  377.  
  378.         if ((s=writeout(fname)) != -1) {
  379.             if(!(gmode&MDTOOL)){
  380.             strcpy(curbp->b_fname, fname);
  381.             curbp->b_flag &= ~BFCHG;
  382.  
  383.             wp = wheadp;                    /* Update mode lines.   */
  384.             while (wp != NULL) {
  385.                         if (wp->w_bufp == curbp)
  386.                 if((Pmaster && s == TRUE) || Pmaster == NULL)
  387.                                 wp->w_flag |= WFMODE;
  388.                         wp = wp->w_wndp;
  389.             }
  390.         }
  391.  
  392.         if(s > 1)
  393.           emlwrite("Wrote %d lines", s);
  394.         else
  395.           emlwrite("Wrote 1 line", NULL);
  396.         }
  397.         return ((s == -1) ? FALSE : TRUE);
  398. }
  399.  
  400.  
  401.  
  402. /*
  403.  * Save the contents of the current
  404.  * buffer in its associatd file. No nothing
  405.  * if nothing has changed (this may be a bug, not a
  406.  * feature). Error if there is no remembered file
  407.  * name for the buffer. Bound to "C-X C-S". May
  408.  * get called by "C-Z".
  409.  */
  410. filesave(f, n)
  411. {
  412.         register WINDOW *wp;
  413.         register int    s;
  414.  
  415.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  416.         return(rdonly());    /* we are in read only mode    */
  417.         if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
  418.                 return (TRUE);
  419.         if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
  420.                 emlwrite("No file name");
  421.         sleep(2);
  422.                 return (FALSE);
  423.         }
  424.  
  425.     emlwrite("Writing...");
  426.         if ((s=writeout(curbp->b_fname)) != -1) {
  427.                 curbp->b_flag &= ~BFCHG;
  428.                 wp = wheadp;                    /* Update mode lines.   */
  429.                 while (wp != NULL) {
  430.                         if (wp->w_bufp == curbp)
  431.               if(Pmaster == NULL)
  432.                                 wp->w_flag |= WFMODE;
  433.                         wp = wp->w_wndp;
  434.                 }
  435.         if(s > 1){
  436.             emlwrite("Wrote %d lines", s);
  437.         }
  438.         else
  439.           emlwrite("Wrote 1 line");
  440.         }
  441.         return (s);
  442. }
  443.  
  444. /*
  445.  * This function performs the details of file
  446.  * writing. Uses the file management routines in the
  447.  * "fileio.c" package. The number of lines written is
  448.  * displayed. Sadly, it looks inside a LINE; provide
  449.  * a macro for this. Most of the grief is error
  450.  * checking of some sort.
  451.  *
  452.  * CHANGES: 1 Aug 91: returns number of lines written or -1 on error, MSS
  453.  */
  454. writeout(fn)
  455. char    *fn;
  456. {
  457.         register int    s;
  458.         register LINE   *lp;
  459.         register int    nline;
  460.     char     line[80];
  461.  
  462.         if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
  463.                 return (-1);
  464.  
  465.         lp = lforw(curbp->b_linep);             /* First line.          */
  466.         nline = 0;                              /* Number of lines.     */
  467.         while (lp != curbp->b_linep) {
  468.                 if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  469.                         break;
  470.                 ++nline;
  471.                 lp = lforw(lp);
  472.         }
  473.         if (s == FIOSUC) {                      /* No write error.      */
  474.                 s = ffclose();
  475.         } else                                  /* Ignore close error   */
  476.                 ffclose();                      /* if a write error.    */
  477.         if (s != FIOSUC)                        /* Some sort of error.  */
  478.                 return (-1);
  479.         return (nline);
  480. }
  481.  
  482.  
  483. /*
  484.  * writetmp - write a temporary file for message text, mindful of 
  485.  *          access restrictions and included text.  If n is true, include
  486.  *          lines that indicated included message text, otw forget them
  487.  */
  488. char *writetmp(f, n)
  489. {
  490.         static   char    fn[NFILEN];
  491.         register int    s;
  492.         register LINE   *lp;
  493.         register int    nline;
  494.  
  495.     tmpname(fn);
  496.     
  497.         if ((s=ffwopen(fn)) != FIOSUC)          /* Open writes message. */
  498.                 return(NULL);
  499.  
  500.     chmod(fn, 0600);            /* fix access rights */
  501.  
  502.         lp = lforw(curbp->b_linep);             /* First line.          */
  503.         nline = 0;                              /* Number of lines.     */
  504.         while (lp != curbp->b_linep) {
  505.         if(n || (!n && lp->l_text[0] != '>'))
  506.                 if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC)
  507.                         break;
  508.                 ++nline;
  509.                 lp = lforw(lp);
  510.         }
  511.         if (s == FIOSUC) {                      /* No write error.      */
  512.                 s = ffclose();
  513.         } else                                  /* Ignore close error   */
  514.                 ffclose();                      /* if a write error.    */
  515.         if (s != FIOSUC){                       /* Some sort of error.  */
  516.             unlink(fn);
  517.                 return(NULL);
  518.     }
  519.         return(fn);
  520. }
  521.  
  522.  
  523. /*
  524.  * The command allows the user
  525.  * to modify the file name associated with
  526.  * the current buffer. It is like the "f" command
  527.  * in UNIX "ed". The operation is simple; just zap
  528.  * the name in the BUFFER structure, and mark the windows
  529.  * as needing an update. You can type a blank line at the
  530.  * prompt if you wish.
  531.  */
  532. filename(f, n)
  533. {
  534.         register WINDOW *wp;
  535.         register int    s;
  536.         char            fname[NFILEN];
  537.  
  538.         if ((s=mlreply("Name: ", fname, NFILEN, QFFILE)) == ABORT)
  539.                 return (s);
  540.         if (s == FALSE)
  541.                 strcpy(curbp->b_fname, "");
  542.         else
  543.                 strcpy(curbp->b_fname, fname);
  544.         wp = wheadp;                            /* Update mode lines.   */
  545.         while (wp != NULL) {
  546.                 if (wp->w_bufp == curbp)
  547.           if(Pmaster == NULL)
  548.                         wp->w_flag |= WFMODE;
  549.                 wp = wp->w_wndp;
  550.         }
  551.     curbp->b_mode &= ~MDVIEW;    /* no longer read only mode */
  552.         return (TRUE);
  553. }
  554.  
  555. /*
  556.  * Insert file "fname" into the current
  557.  * buffer, Called by insert file command. Return the final
  558.  * status of the read.
  559.  */
  560. ifile(fname)
  561. char    fname[];
  562. {
  563.         register LINE   *lp0;
  564.         register LINE   *lp1;
  565.         register LINE   *lp2;
  566.         register int    i;
  567.         register BUFFER *bp;
  568.         register int    s;
  569.         register int    nbytes;
  570.         register int    nline;
  571.     int        lflag;        /* any lines longer than allowed? */
  572.         char            line[NLINE];
  573.         char     dbuf[128];
  574.         register char    *dbufp;
  575.  
  576.         bp = curbp;                             /* Cheap.               */
  577.         bp->b_flag |= BFCHG;            /* we have changed    */
  578.     bp->b_flag &= ~BFTEMP;            /* and are not temporary*/
  579.         if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
  580.                 goto out;
  581.         if (s == FIOFNF) {                      /* File not found.      */
  582.         emlwrite("No such file: %s",fname);
  583.         return(FALSE);
  584.         }
  585.         emlwrite("Inserting %s.", fname);
  586.  
  587.     /* back up a line and save the mark here */
  588.     curwp->w_dotp = lback(curwp->w_dotp);
  589.     curwp->w_doto = 0;
  590.     curwp->w_markp = curwp->w_dotp;
  591.     curwp->w_marko = 0;
  592.  
  593.         nline = 0;
  594.     lflag = FALSE;
  595.         while ((s=ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) {
  596.         if (s == FIOLNG)
  597.             lflag = TRUE;
  598.                 nbytes = strlen(line);
  599.                 if ((lp1=lalloc(nbytes)) == NULL) {
  600.                         s = FIOERR;             /* Keep message on the  */
  601.                         break;                  /* display.             */
  602.                 }
  603.         lp0 = curwp->w_dotp;    /* line previous to insert */
  604.         lp2 = lp0->l_fp;    /* line after insert */
  605.  
  606.         /* re-link new line between lp0 and lp2 */
  607.         lp2->l_bp = lp1;
  608.         lp0->l_fp = lp1;
  609.         lp1->l_bp = lp0;
  610.         lp1->l_fp = lp2;
  611.  
  612.         /* and advance and write out the current line */
  613.         curwp->w_dotp = lp1;
  614.                 for (i=0; i<nbytes; ++i)
  615.                         lputc(lp1, i, line[i]);
  616.                 ++nline;
  617.         }
  618.         ffclose();                              /* Ignore errors.       */
  619.     curwp->w_markp = lforw(curwp->w_markp);
  620.         if (s == FIOEOF) {                      /* Don't zap message!   */
  621.             sprintf(dbuf,"Inserted %d line%s",nline,(nline>1) ? "s" : "");
  622.         emlwrite(dbuf);
  623.         }
  624.     if (lflag) {
  625.         sprintf(dbuf,"Inserted %d line%s, Long lines wrapped.",
  626.             nline, (nline>1) ? "s" : "");
  627.         emlwrite(dbuf);
  628.         }
  629. out:
  630.     /* advance to the next line and mark the window for changes */
  631.     curwp->w_flag |= WFHARD;
  632.  
  633.     /* copy window parameters back to the buffer structure */
  634.     curbp->b_dotp = curwp->w_dotp;
  635.     curbp->b_doto = curwp->w_doto;
  636.     curbp->b_markp = curwp->w_markp;
  637.     curbp->b_marko = curwp->w_marko;
  638.  
  639.         if (s == FIOERR)                        /* False if error.      */
  640.                 return (FALSE);
  641.         return (TRUE);
  642. }
  643.